#pragma once

#include "../comm/dispatch.hpp"
#include "rpc_router.hpp"
#include "rpc_registry.hpp"
#include "../client/rpc_client.hpp"
#include"rpc_topic.hpp"

namespace Server
{
    using namespace Dispatch;
    using namespace Client;
    class RegistryServer
    {
    public:
        using ptr = shared_ptr<RegistryServer>;
        RegistryServer(int port) :
             _pd_manger(make_shared<PDManger>()),
             _dispatcher(make_shared<Dispatcher>())
        {
            auto service_cb = bind(&PDManger::OnServiceRequest, _pd_manger.get(), placeholders::_1, placeholders::_2);
            _dispatcher->RegisterHander<ServiceRequest>(Mtype::REQ_SERVICE, service_cb);

            _server = ServerFactory::create(port);
            auto message_cb = bind(&Dispatch::Dispatcher::OnMessage, _dispatcher.get(),
                                   placeholders::_1, placeholders::_2);
            _server->SetMessageCB(message_cb);

            auto close_cb = bind(&RegistryServer::OnConnShutDown, this, placeholders::_1);
            _server->SetCloseCB(close_cb);
        }
        void Start()
        {
            _server->Start();
        }

    private:
        void OnConnShutDown(const BaseConnection::ptr &conn)
        {
            _pd_manger->OnConnShutdown(conn);
        }

    private:
        PDManger::ptr _pd_manger;
        Dispatch::Dispatcher::ptr _dispatcher;
        BaseServer::ptr _server;
    };

    class RpcServer
    {
    public:
        using ptr = shared_ptr<RpcServer>;
        // Rpc_server有两套地址信息
        // 1.rpc服务提供端地址信息--是rpc服务器对外访问地址（云服务器--监听地址和访问地址不同）
        // 2.注册中心服务端地址信息--启用服务注册后，连接注册中心进行服务注册
        RpcServer(const Address &access_addr, bool enable_registry = false, const Address &reg_server_addr = Address())
            : _enable_registry(enable_registry),
             _access_addr(access_addr), 
             _router(make_shared<RpcRouter>()),
             _dispatcher(make_shared<Dispatcher>())
        {
            if (enable_registry)
            {
                _reg_client = make_shared<RegistryClient>(reg_server_addr.first, reg_server_addr.second);
            }
            // 当前是一个RpcServer成员，提供Rpc服务
            auto rpc_cb = std::bind(&Server::RpcRouter::OnRpcRequest, _router.get(),
                                    placeholders::_1, placeholders::_2);
            _dispatcher->RegisterHander<RpcRequest>(Mtype::REQ_RPC, rpc_cb); // 注册映射关系

            _server = ServerFactory::create(access_addr.second);
            auto message_cb = bind(&Dispatch::Dispatcher::OnMessage, _dispatcher.get(),
                                   placeholders::_1, placeholders::_2);
            _server->SetMessageCB(message_cb);
        }
        void RegistryMethod(const ServiceDescribe::ptr &service)
        {
            if (_enable_registry)
            {
                _reg_client->RegistryMethod(service->Methodname(), _access_addr);
            }
            _router->RegisterMethod(service);
        }
        void Start()
        {
            _server->Start();
        }

    private:
        bool _enable_registry;
        Client::RegistryClient::ptr _reg_client;
        Address _access_addr;
        RpcRouter::ptr _router;
        Dispatch::Dispatcher::ptr _dispatcher;
        BaseServer::ptr _server;
    };


    class TopicServer
    {
    public:
        using ptr = shared_ptr<TopicServer>;
        TopicServer(int port) :
             _topic_manger(make_shared<TopicManger>()),
             _dispatcher(make_shared<Dispatcher>())
        {
            auto topic_cb = bind(&TopicManger::OnTopicRequest, _topic_manger.get(), placeholders::_1, placeholders::_2);
            _dispatcher->RegisterHander<TopicRequest>(Mtype::REQ_TOPIC, topic_cb);

            _server = ServerFactory::create(port);
            auto message_cb = bind(&Dispatch::Dispatcher::OnMessage, _dispatcher.get(),
                                   placeholders::_1, placeholders::_2);
            _server->SetMessageCB(message_cb);

            auto close_cb = bind(&TopicServer::OnConnShutDown, this, placeholders::_1);
            _server->SetCloseCB(close_cb);
        }
        void Start()
        {
            _server->Start();
        }

    private:
        void OnConnShutDown(const BaseConnection::ptr &conn)
        {
            _topic_manger->OnShutDown(conn);
        }

    private:
        Server::TopicManger::ptr _topic_manger;
        Dispatch::Dispatcher::ptr _dispatcher;
        BaseServer::ptr _server;
    };

}
